package com.cy.detectsys.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cy.detectsys.entity.DataCenterInfo;
import com.cy.detectsys.entity.IpNetCloudServiceInfo;
import com.cy.detectsys.entity.ProbeResult;
import com.cy.detectsys.entity.ProbeResultConnectCloud;
import com.cy.detectsys.entity.vo.DataCenterInfoVo;
import com.cy.detectsys.entity.vo.ProbeResultConnectCloudVo;
import com.cy.detectsys.mapper.DataCenterInfoMapper;
import com.cy.detectsys.mapper.IpNetCloudServiceInfoMapper;
import com.cy.detectsys.mapper.ProbeResultMapper;
import com.cy.detectsys.model.vo.AssertStatisticVo;
import com.cy.detectsys.service.ProbeResultConnectCloudService;
import com.cy.detectsys.mapper.ProbeResultConnectCloudMapper;
import com.cy.detectsys.util.IPRangeConverter;
import com.cy.detectsys.util.R;
import jakarta.annotation.Resource;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.net.UnknownHostException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author cyan
 * @description 针对表【probe_result_connect_cloud】的数据库操作Service实现
 * @createDate 2024-06-12 11:07:24
 */
@Service
public class ProbeResultConnectCloudServiceImpl extends ServiceImpl<ProbeResultConnectCloudMapper, ProbeResultConnectCloud>
        implements ProbeResultConnectCloudService {

    @Resource
    private ProbeResultMapper probeResultMapper;

    @Resource
    private IpNetCloudServiceInfoMapper ipNetCloudServiceInfoMapper;

    @Resource
    private ProbeResultConnectCloudMapper probeResultConnectCloudMapper;
    @Resource
    private DataCenterInfoMapper dataCenterInfoMapper;

    @Override
    public R querySimpleInfo(String centerName) {
        HashMap<String, Integer> centerInfo = new HashMap<>();
        //先从probe_result_connect_cloud表中拿到所有的IP
        List<String> ipList = baseMapper.queryIndependenceIp(centerName);

        if (ipList.size() == 0) {
            centerInfo.put("ipSize", ipList.size());
            centerInfo.put("assetSize", ipList.size());
            return R.ok(centerInfo);
        }
        centerInfo.put("ipSize", ipList.size());
        // 再根据ip查询资产数量
        QueryWrapper<ProbeResult> probeResultQueryWrapper = new QueryWrapper<>();
        probeResultQueryWrapper.in("ip", ipList);
        List<ProbeResult> probeResults = probeResultMapper.selectList(probeResultQueryWrapper);
        centerInfo.put("assetSize", probeResults.size());
        return R.ok(centerInfo);
    }

    @Override
    public R queryFullInfo(String centerName) {
        //查询数据中心的端口、 协议、 server 、 Ip段
        /**
         *
         * 端口： 根据数据中心 从probe_result_connect_cloud表中拿到所有的IP  再去统计ip 在probe_result 的端口
         *
         * 协议： 根据数据中心 从probe_result_connect_cloud表中拿到所有的IP  再去统计ip 在probe_result port
         *
         * Server： 根据数据中心 从probe_result_connect_cloud表中拿到所有的IP  再去统计ip 在probe_result Banner 字段中 WebBanner 中 Server
         *
         * ip段： 根据数据中心 从ip_net_cloud_service_info 拿到 ip段，找到这个段下ip的数量
         *
         */

        HashMap<String, List> result = new HashMap<>();

        List<ProbeResult> assets = getAsset(centerName);
        List<AssertStatisticVo> orderPorts = getOrderPorts(assets);
        List<AssertStatisticVo> orderProtocols = getOrderProtocols(assets);
        List<AssertStatisticVo> orderServers = getOrderServers(assets);
        QueryWrapper<IpNetCloudServiceInfo> ipNetCloudServiceInfoQW = new QueryWrapper<>();
        ipNetCloudServiceInfoQW.eq("data_center_name", centerName);
        List<IpNetCloudServiceInfo> ipNetCloudServiceInfos = ipNetCloudServiceInfoMapper.selectList(ipNetCloudServiceInfoQW);
        List<AssertStatisticVo> orderIps = getOrderIps(ipNetCloudServiceInfos);
        result.put("orderPorts", orderPorts);
        result.put("orderProtocols", orderProtocols);
        result.put("orderServers", orderServers);
        result.put("orderIps", orderIps);
        return R.ok(result);
    }

    @Override
    public R queryCloudInfo(String centerName) {
        return null;
    }


    private List<AssertStatisticVo> getOrderIps(List<IpNetCloudServiceInfo> ipNetCloudServiceInfos) {
        HashMap<String, Integer> assetsMap = new HashMap<>();
        for (IpNetCloudServiceInfo ipNetCloudServiceInfo : ipNetCloudServiceInfos) {
            String ipNet = ipNetCloudServiceInfo.getIpNet();
            if (StringUtils.isNotBlank(ipNet)) {
                try {
                    String[] minMaxIPs = IPRangeConverter.convertCidrToRange(ipNet);
                    if (minMaxIPs != null && minMaxIPs.length == 2) {
                        String minIP = minMaxIPs[0];
                        String maxIP = minMaxIPs[1];
                        Integer count = probeResultMapper.countByIps(minIP, maxIP);
                        assetsMap.put(ipNet, count);
                    }
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
            }
        }
        return getOrderedList(assetsMap);
    }


    private List<AssertStatisticVo> getOrderServers(List<ProbeResult> assets) {
        HashMap<String, Integer> assetsMap = new HashMap<>();
        //统计字段值出现的次数
        for (ProbeResult asset : assets) {
            String banners = asset.getBanners();
            if (StringUtils.isNotBlank(banners)) {
                JSONArray bannersArray = JSONUtil.parseArray(banners);
                Map<String, Object> bannersMap = (Map<String, Object>) bannersArray.get(0);
                if (bannersMap != null) {
                    Map<String, Object> webBannerMap = (Map<String, Object>) bannersMap.get("WebBanner");
                    if (webBannerMap != null) {
                        String server = (String) webBannerMap.get("Server");
                        if (StringUtils.isNotBlank(server)) {
                            assetsMap.put(server, assetsMap.getOrDefault(server, 0) + 1);
                        }
                    }
                }
            }
        }
        return getOrderedList(assetsMap);
    }

    private List<AssertStatisticVo> getOrderProtocols(List<ProbeResult> assets) {
        HashMap<String, Integer> assetsMap = new HashMap<>();
        //统计字段值出现的次数
        for (ProbeResult asset : assets) {
            String protocol = asset.getProtocol();
            assetsMap.put(protocol, assetsMap.getOrDefault(protocol, 0) + 1);
        }
        return getOrderedList(assetsMap);
    }


    private List<AssertStatisticVo> getOrderPorts(List<ProbeResult> assets) {
        HashMap<String, Integer> assetsMap = new HashMap<>();
        //统计字段值出现的次数
        for (ProbeResult asset : assets) {
            String port = asset.getPort();
            assetsMap.put(port, assetsMap.getOrDefault(port, 0) + 1);
        }
        return getOrderedList(assetsMap);
    }


    List<ProbeResult> getAsset(String centerName) {
        //先从probe_result_connect_cloud表中拿到所有的IP
        List<String> ipList = baseMapper.queryIndependenceIp(centerName);
        if (CollectionUtil.isEmpty(ipList)) {

            return new ArrayList<>();
        }
        // 再根据ip查询资产数量
        QueryWrapper<ProbeResult> probeResultQueryWrapper = new QueryWrapper<>();
        probeResultQueryWrapper.in("ip", ipList);
        List<ProbeResult> probeResults = probeResultMapper.selectList(probeResultQueryWrapper);
        return probeResults;
    }

    // 根据字段值的出现次数进行排序
    public List<AssertStatisticVo> getOrderedList(HashMap<String, Integer> assetsMap) {
        ArrayList<AssertStatisticVo> assertStatisticVos = new ArrayList<>();
        for (String port : assetsMap.keySet()) {
            AssertStatisticVo assertStatisticVo = new AssertStatisticVo();
            assertStatisticVo.setCount(assetsMap.get(port));
            assertStatisticVo.setField(port);
            assertStatisticVos.add(assertStatisticVo);
        }

        List<AssertStatisticVo> orderedList = assertStatisticVos.stream().sorted(new Comparator<AssertStatisticVo>() {
            @Override
            public int compare(AssertStatisticVo o1, AssertStatisticVo o2) {
                return o1.getCount() > o2.getCount() ? -1 : o1.getCount() == o2.getCount() ? 0 : 1;
            }
        }).collect(Collectors.toList());


        if (orderedList.size() > 5) {
            return orderedList.subList(0, 4);
        }
        return orderedList;
    }





}




